# !/usr/bin/python3
# -*- coding: utf-8 -*-
# @Time    : 2019/8/19 14:15
# @Author  : LiHaowen
# @Email   : lihaowen2017@163.com
import uuid
from asgiref.sync import async_to_sync, sync_to_async  # 异步变同步, 同步变异步
# from channels.db import database_sync_to_async  # django orm 同步变异步
from django.shortcuts import render, get_object_or_404  # get查询，如果查询结果为空则直接返回404；后面的代码无法执行
from django.http import HttpResponse, JsonResponse
from django.contrib.auth import get_user_model
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.decorators.http import require_http_methods
from django.views.generic import ListView
from django.template.loader import render_to_string

from web_ask.messager.models import Message
from web_ask.helpers import ajax_required
from web_ask.notifications.views import messager_notification_handler

from channels.layers import get_channel_layer


class MessagesListView(LoginRequiredMixin, ListView):
    model = Message
    template_name = "messager/message_list.html"

    def get_context_data(self, *, object_list=None, **kwargs):
        context = super(MessagesListView, self).get_context_data()
        # 获取除当前登录用户外的所有用户，按最近登录时间降序排列(is_active=True)激活用户
        context["users_list"] = get_user_model().objects.filter(is_active=True).exclude(
            username=self.request.user
        ).order_by("-last_login")[:10]
        # 最近一次私信互动的用户
        last_conversation = Message.objects.get_most_recent_conversation(self.request.user)
        context["active"] = last_conversation.username
        return context

    def get_queryset(self):
        """最近私信活动的内容"""
        # 获取最近一次与登录用户私信的用户
        active_user = Message.objects.get_most_recent_conversation(self.request.user)
        # 获取两个用户的私信并集
        return Message.objects.get_conversation(self.request.user, active_user)


class ConversationListView(MessagesListView):
    """与指定用户的私信内容"""

    def get_context_data(self, *, object_list=None, **kwargs):
        context = super().get_context_data()
        context["active"] = self.kwargs["username"]  # 与指定用户的私信，前端传递的username
        return context

    def get_queryset(self):
        """选中用户的私信内容"""
        # get_object_or_404 传递模型和参数
        active_user = get_object_or_404(get_user_model(), username=self.kwargs["username"])
        return Message.objects.get_conversation(self.request.user, active_user)


@login_required
@ajax_required
@require_http_methods(["POST"])
def send_message(request):
    """发送信息，AJAX POST 请求"""
    sender = request.user
    recipient_username = request.POST["to"]
    recipient = get_user_model().objects.filter(username=recipient_username).first()
    message = request.POST["message"]
    if len(message.strip()) != 0 and sender != recipient:
        # 用户发送消息不能为空，且发送者不能为自己
        msg = Message.objects.create(
            uuid_id=uuid.uuid4(),  # 如果不在这里创建uuid，使用字段中默认的uuid会，uuid重复
            sender=sender,
            recipient=recipient,
            message=message
        )
        # 私信的内容发送到consumer的频道组中
        # 获取所在的频道
        channel_layer = get_channel_layer()
        # group_send(组，消息内容)，将消息发送到组中
        payload = {
            "type": "receive",  # 固定字段代表consumer中的receive函数，接受websocket消息
            "message": render_to_string("messager/single_message.html", {"message": msg}),  # 传递的消息 模板渲染成字符串
            "sender": sender.username  # 发送者
        }
        # group_send(group:所在组-接收者的Username, message:消息内容)
        async_to_sync(channel_layer.group_send)(recipient_username, payload)  # 异步变同步
        # 通知私信接收者
        messager_notification_handler(sender, recipient, "R", msg)
        return render(request, "messager/single_message.html", {"message": msg})
    return HttpResponse()

#  已经使用websocket推送
# @login_required
# @ajax_required
# @require_http_methods(["GET"])
# def receive_message(request):
#     """接受信息，AJAX GET 请求"""
#     message_id = request.GET["message_id"]
#     msg = Message.objects.get(pk=message_id)
#     return render(request, "messager/single_message.html", {"message": msg})
